#!/usr/bin/env perl
=begin
 AS2Dac - Auto Commenting for AS2.0 Classes and Interfaces
 http://code.google.com/p/as2dacperl

 Author: Jason Milkins / http://mentalaxis.com
 Copyright (C) 2006/2008  Jason Milkins / mentalaxis.com

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
=cut

package Main;

use Getopt::Std;
use AutoJavaDoc;
use AutoNaturalDoc;

# Manage command line options
%option=();
$Getopt::Std::STANDARD_HELP_VERSION = true;
getopts("pnjlV:tT:a:e:c:o:",\%option);

# Create divider for console messages
$divider = ('=' x 98);

# Get input output settings
$inFile = $option{c} or usageMessage();
$outFile = ($option{o}) ? $option{o} : $option{c};

# Determine Author String;
if ($option{a} && $option{e}) {
	$inAuthor = $option{a} . " / " . $option{e};
} else {
	if ($option{a}) {
		$inAuthor = $option{a};
	}
	
	if ($option{e}) {
		$inAuthor = $option{e};
	}
} 

# logging? - otherwise silent.
if ($option{l}) {
	 logInfo();
}

# is a class (0 = interface)
$isClass = 1;

# Init loop vars...
$braceCount        = 0;
$blockCommentCount = 0;

# Run main loop using the first parameter passed at the command line...
$documented = docFile($inFile);

# output the $documented version to the outFile $ARGV[1])
outputDoc( $outFile, $documented );

=begin
 sub: outputDoc
=cut
sub outputDoc {
	my ( $fileName, $outputText ) = @_;
	open( OUTFILE, "> $fileName" )
	  or die "File Error: $fileName write error: $!\n";
	select OUTFILE;
	print $outputText;
	close OUTFILE;
}


=begin
 sub: docFile
=cut
sub docFile {
	my ($fileName) = @_;

	#init Output
	$output = "";

	#init prevDone;
	$previous = 0;

	# open file...
	open SOURCE, "< $fileName"
	  or die "File Error: $fileName cannot be read: $!\n";

	# Read the file into an array of lines...
	@lines = <SOURCE>;
	close SOURCE;
	for my $line (@lines) {
		if ( $previous != 1 ) {
			if ( $line =~ m!\*/! ) {
				$previous = 1;
			} else {
				$previous = 0;
			}

			# Update block comment count
			$openBlockComment = $line =~ m!/\*!;
			$blockCommentCount += $openBlockComment;
			$closeBlockComment = $line =~ m!\*/!;
			$blockCommentCount -= $closeBlockComment;

			# If we are not inside a block comment check/document the line...
			if ( $blockCommentCount == 0 ) {

				# Update brace count
				$openBrace = $line =~ m/{/;
				$braceCount += $openBrace;
				$closeBrace = $line =~ m/}/;
				$braceCount -= $closeBrace;

				# determine the documentation for the current line, and return it.
				$doc = docline( $line, $braceCount, $docType);

				# send documentation to output
				$output .= $doc;
			}
		} else {
			$previous = 0;
		}
		$output .= $line;
	}

	#return output
	return $output;
}


=begin
  sub: docline
  Process a line and build documentation for class, interface and members.
=cut
sub docline {
	my ( $inLine, $braceCount, $docStyle ) = @_;

	$lineDoc      = "";
	$currentBrace = $inLine =~ m/{/;

	# Determine TODO marking...
	if ($option{t}) {
		$TODO = ($option{T} ne "") ? $option{T} : "TODO";
		$AutoNaturalDoc::TODO = $TODO;
		$AutoJavaDoc::TODO = $TODO;
	}
	
	# Default to JavaDoc
	if(not $option{n}) {
		$lineDoc = AutoJavaDoc->checkClass( $inLine, $braceCount, $currentBrace, $inAuthor, $option{V} );
		if ( $lineDoc ne "" ) { return $lineDoc; }
		$lineDoc = AutoJavaDoc->checkClassProperty( $inLine, $braceCount, $currentBrace, $option{p} );
		if ( $lineDoc ne "" ) { return $lineDoc; }		
		$lineDoc = AutoJavaDoc->checkClassMethod( $inLine, $braceCount, $currentBrace );
		if ( $lineDoc ne "" ) { return $lineDoc; }
		$lineDoc = AutoJavaDoc->checkInterface( $inLine, $braceCount, $currentBrace, $inAuthor, $option{V} );
		if ( $lineDoc ne "" ) { return $lineDoc; }
		$lineDoc = AutoJavaDoc->checkInterfaceMethod( $inLine, $braceCount, $currentBrace );
		if ( $lineDoc ne "" ) { return $lineDoc; }
	} else {
		$lineDoc = AutoNaturalDoc->checkClass( $inLine, $braceCount, $currentBrace, $inAuthor, $option{V} );
		if ( $lineDoc ne "" ) { return $lineDoc; }
		$lineDoc = AutoNaturalDoc->checkClassProperty( $inLine, $braceCount, $currentBrace, $option{p} );
		if ( $lineDoc ne "" ) { return $lineDoc; }
		$lineDoc = AutoNaturalDoc->checkClassMethod( $inLine, $braceCount, $currentBrace, $option{p} );
		if ( $lineDoc ne "" ) { return $lineDoc; }
		$lineDoc = AutoNaturalDoc->checkInterface( $inLine, $braceCount, $currentBrace, $inAuthor, $option{V} );
		if ( $lineDoc ne "" ) { return $lineDoc; }
		$lineDoc = AutoNaturalDoc->checkInterfaceMethod( $inLine, $braceCount, $currentBrace );
		if ( $lineDoc ne "" ) { return $lineDoc; }	
	}
}

=begin
 sub: HELP_MESSAGE

 Display the usage message when incorrect options 
 are passed, or when option -h is used.
=cut
sub HELP_MESSAGE {	
print STDOUT <<"EOF";
 $divider
   AS2Dac creates documentation comment stubs in As2.0 class files.

   Example:
      as2dac.pl -c MyClass.as -o MyCommentedClass.as -j -a 'jason milkins' -e jason\@mentalaxis.com -V 1.0

   Usage:
      as2dac.pl [options]

   Options:  
      -c filename          : AS2.0 Class file to auto comment
      -o filename          : Output to another file

      -j                   : Javadoc style (default)
      -n                   : Naturaldocs style

      -p                   : Only add doc comment stubs to public members

      -a 'author name'     : Author name (in quotes if it contains spaces)
      -e email\@domain.org  : Author email

      -t                   : Add TODO notes to comment stubs
      -T 'message'         : If -t is used, customise TODO string                             

      -V 'version'         : AS2.0 class Version string

      -l                   : log output. (default is silent)
      
      --help               : this message

 $divider
   All the usual disclaimers apply - use at your own risk
   http://code.google.com/p/as2dacperl for more info
 $divider
   Licenced under GNU General Public License, version 2
EOF

exit;
}

=begin
 sub: VERSION_MESSAGE

 Standard version message
=cut
sub VERSION_MESSAGE {
print STDOUT <<"EOF";
 $divider
   ActionScript 2.0 Documentation Auto-Commenting : AS2Dac v1.1   
EOF
}

=begin
 sub: usageMessage

 Standard version message

=cut
sub usageMessage {
	VERSION_MESSAGE();
	HELP_MESSAGE();
}

=begin
 sub: logInfo

 Print the options from getOpts to stdout
=cut
sub logInfo {
	$docType = (not $option{n}) ? "JavaDoc" : "NaturalDocs"; 
	printTimeStamp();
	print STDOUT " : $inFile > $outFile [ author: $inAuthor, version: $inVersion todo: '$TODO', doc: ".
	 $docType
	." ]\n";
}
=begin
 sub: printTimeStamp
=cut
sub printTimeStamp {
	($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
	printf STDOUT "%4d-%02d-%02d %02d:%02d:%02d",$year+1900,$mon+1,$mday,$hour,$min,$sec;		
}